/*
 * FVoronoi.cpp
 *
 *  Created on: May 13, 2012
 *      Author: marchi
 */

#include "FVoronoi.h"
const int NTYPES=3;
struct VolAreaInd{
	float Vol,area[NTYPES];
	int n;
	int Type;
	bool bContact;
	VolAreaInd():Vol(0),n(-1),Type(-1),bContact(false){for(int o=0;o<NTYPES;o++) area[o]=0.0;};
};
class ContactSolute{
public:
	bool operator()(VolAreaInd x){return (!x.bContact);}
};
class Solute{
public:
	bool operator()(VolAreaInd x){return x.Type != Slt;}
};
class Solvent{
public:
	bool operator()(VolAreaInd x){return x.Type != Sol;}
};

FVoronoi::FVoronoi(int n, const vector<string> & s, bool bH): Voronoi(){
	nr=n;
	Vol=new double [nr];
	Neighs=new vector<int> [nr];
	Surface=new vector<double> [nr];
	label=new string [nr];
	types=new int [nr];

	for(int i=0;i<nr;i++){
		label[i]=s[i];
		if(bH || label[i].compare(0,1,h,0,1)) cindex.push_back(i);
	}
}
std::ofstream & operator<<(std::ofstream & fout , FVoronoi  & y){
	vector<VolAreaInd> tmp(y.nr);
	for(int o=0;o<y.nresid;o++) {
		vector<int> & cindex=ResidueCM::getind(o);
		bool bC=false;
		for(unsigned int ia=0;ia<cindex.size();ia++){
			int i=cindex[ia];
			tmp[i].Vol=static_cast<float> (y.Vol[i]*1000.0);
			for(unsigned int p=0;p<y.Neighs[i].size();p++){
				tmp[i].area[y.getTypes(y.Neighs[i][p])]+=static_cast<float> (y.Surface[i][p]*100.0);
			}
			if(tmp[i].area[0]) bC=true;
			tmp[i].n=i+1;
			tmp[i].Type=y.getTypes(i);
		}
		for(unsigned int ia=0;ia<cindex.size();ia++)
			tmp[cindex[ia]].bContact=bC;
	}
	vector<VolAreaInd> tmp0(tmp);
	tmp0.erase(std::remove_if(tmp0.begin(),tmp0.end(),Solute()),tmp0.end());
	tmp.erase(std::remove_if(tmp.begin(),tmp.end(),Solvent()),tmp.end());
	tmp.erase(std::remove_if(tmp.begin(),tmp.end(),ContactSolute()),tmp.end());
	vector<VolAreaInd> data;

	copy(tmp0.begin(),tmp0.end(),back_inserter(data));
	copy(tmp.begin(),tmp.end(),back_inserter(data));
	tmp.clear();
	tmp0.clear();

	int F4bytes=2*INT;
	int nstep=static_cast<int> (y.time);
	int nat=static_cast<int> (data.size());
	fout.write(reinterpret_cast<char *> (&F4bytes),sizeof(F4bytes));
		fout.write(reinterpret_cast<char *> (&nstep),sizeof(nstep));
		fout.write(reinterpret_cast<char *> (&nat),sizeof(nat));
	fout.write(reinterpret_cast<char *> (&F4bytes),sizeof(F4bytes));

	F4bytes=9*DOUBLE;
	double co[DIM][DIM];
	for(int o=0;o<DIM;o++)
		for(int p=0;p<DIM;p++)
			co[o][p]=y.co[o][p];

	fout.write(reinterpret_cast<char *> (&F4bytes),sizeof(F4bytes));
		fout.write(reinterpret_cast<char *> (co),sizeof(co));
	fout.write(reinterpret_cast<char *> (&F4bytes),sizeof(F4bytes));

	F4bytes=(INT+3*FLOAT)*nat;
	fout.write(reinterpret_cast<char *> (&F4bytes),sizeof(F4bytes));
	for(int n=0;n<nat;n++){
		int iat=data[n].n;
		float mydata[3]={data[n].Vol, data[n].area[0],data[n].area[1]};
		fout.write(reinterpret_cast<char *> (&iat),sizeof(iat));
		fout.write(reinterpret_cast<char *> (mydata),sizeof(mydata));
	}
	fout.write(reinterpret_cast<char *> (&F4bytes),sizeof(F4bytes));
	return fout;
}
FVoronoi::~FVoronoi() {
	// TODO Auto-generated destructor stub
}

